package com.itlong.cloud.network.tcp.mina.server;

import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.network.tcp.mina.entity.Message;
import com.itlong.cloud.network.tcp.mina.manage.SessionManage;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.springframework.stereotype.Component;

@Component
public class ServerHandler extends IoHandlerAdapter {
	private static final Logger LOG = LoggerFactory.getLogger(ServerHandler.class);

	private final int IDLE = 1800;
	private SessionManage sm ;  //与一卡通所有项目的TCP会话管理类

	public ServerHandler(){
		sm = SessionManage.newInstance();
	}

	@Override
	public void sessionCreated(IoSession session) {
		//LOG.error("[" + session.getRemoteAddress().toString() + "] 链接 .");
		//LOG.info(String.format("创建了与一卡通客户端的连接:%s",getAddressInfoBySession(session)));
	}


	@Override
	public void sessionOpened(IoSession session) throws Exception {
		session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, IDLE);
//		LOG.info(String.format("开启了与一卡通客户端:%s的连接",getAddressInfoBySession(session)));
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		String key = (String) session.getAttribute("sid");
		if (StringUtils.isNotBlank(key)){
			sm.delSession(key);
//			LOG.info(String.format("与一卡通客户端:%s的连接:%s已经关闭了",key,getAddressInfoBySession(session)));
		}

	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {
		String key = (String)session.getAttribute("sid");
		//LOG.info(String.format("一卡通客户端:%s的连接:%s成为空闲会话,准备强制关闭!",key,getAddressInfoBySession(session)));
		session.close(false);
	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		String key = (String)session.getAttribute("sid");
		String data = convertIoMessageToStr(message);
		//LOG.error(String.format("向一卡通客户端%s的连接:%s发送了数据:%s",key,getAddressInfoBySession(session),data));
	}



	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		String key = (String) session.getAttribute("sid");
		if (StringUtils.isNotBlank(key)){
			sm.delSession(key);
		}
//		LOG.error(String.format("与一卡通客户端：%s的连接:%s 发生异常:%s.",key,getAddressInfoBySession(session),cause.getMessage()));
		session.close(false);
	}

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		if(session == null){
			LOG.info("【接收一卡通客户端消息session异常】");
			return ;
		}
		String receiveMsg =  message.toString();
//		if(StringUtils.isEmpty(message.toString())){
//			session.write("{\"msgCode\":\"0\",\"msg\":\"空字符串\"}");
//			return ;
//		}
		//LOG.info(String.format("接收到来自一卡通客户端连接:%s的数据:%s",getAddressInfoBySession(session),receiveMsg));

		Message cmdMsg = JSONObject.parseObject(receiveMsg,Message.class);
		String key = cmdMsg.getId();
		if((cmdMsg == null) || (cmdMsg.getAct() == null) || (StringUtils.isBlank(key))){
			LOG.info(String.format("接收到来自一卡通客户端:%s 的非法数据:%s",getAddressInfoBySession(session),message));
			return ;
		}
		boolean sessionChanged = false;
		String sessionChangeMsg =  "";
		IoSession oldSession = sm.getSession(key);
		if (oldSession == null){
			//原项目对应的会话连接为空，则临时加入
			//LOG.info(String.format("添加了新的一卡通项目:%s会话连接：%s",key,getAddressInfoBySession(session)));
			sm.addSession(key, session);
		} else {
			//原项目对应的会话连接若已存在，则判断是否是新会话,
			sessionChanged = !StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty(
					getAddressInfoBySession(oldSession),getAddressInfoBySession(session));
			if (sessionChanged){
				//session.setAttribute("sid", key);
				sessionChangeMsg = String.format("SmartCard project:%s already have a session:%s and can not receive new sessions:%s",
						cmdMsg.getId(),getAddressInfoBySession(oldSession),getAddressInfoBySession(session));
//				LOG.error(sessionChangeMsg);
				if (sessionChanged){
					session.write("{\"msgCode\":\"1\",\"msg\":\""+ sessionChangeMsg + "\"}");
					session.close(false);
					return;
				}

			}
		}
		switch (cmdMsg.getAct()) {
			case login:
//				if(cache != null&&cache.isConnected() && session!=cache){
//					cache.close(false);
//				}
				session.setAttribute("sid", key);
				session.write("{\"msgCode\":\"0\"}");

//				LOG.info(String.format("一卡通项目:%s %s登录服务成功",cmdMsg.getId(),getAddressInfoBySession(session)));
				break;

			case loginout:
				session.write("{\"msgCode\":\"0\"}");
				//LOG.info(String.format("一卡通项目:%s %s登录注销成功",cmdMsg.getId(),getAddressInfoBySession(session)));
				if(session != null&&session.isConnected()){
					session.close(false);
				}
				sm.addSession(cmdMsg.getId(), session);
				break;
			case msg:
				session.write("{\"msgCode\":\"0\"}");
				break;
			default:
				session.write("{\"msgCode\":\"0\"}");  //可能充当心跳包作用
				break;
		}
	}



	/**
	 * <desc>
	 * 根据客户端会话，获取IP地址，IP:Port.
	 * </desc>
	 *
	 * @param session 客户端会话
	 * @return IP地址，IP:Port.
	 * @author LewisLouis
	 * @createDate 2018/01/20
	 */
	private String getAddressInfoBySession(IoSession session) {
		String remoteAddress = "";
		if ((null == session) || (null == session.getRemoteAddress())) {
			//LOG.error(String.format("Session:%s is invalid, can not get remoteAddress", session));
			return remoteAddress;
		}
		remoteAddress = session.getRemoteAddress().toString();

		return remoteAddress;
	}



	/**
	 * <desc>
	 * 将IO信息转换为字符串.
	 * </desc>
	 *
	 * @param message Io信息
	 * @return xx
	 * @author LewisLouis
	 * @createDate 2018/01/20
	 */
	private String convertIoMessageToStr(Object message) {
		String data = "";
		if (message instanceof  IoBuffer){
			IoBuffer bbuf = (IoBuffer) message;
			byte[] byten = new byte[bbuf.limit()];
			bbuf.get(byten, bbuf.position(), bbuf.limit());
			data = new String(byten);
		} else {
			data = message.toString();
		}

		return data;
	}

}
